package com.itheima.a15;

import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import org.springframework.aop.aspectj.AspectJExpressionPointcut;
import org.springframework.aop.framework.ProxyFactory;
import org.springframework.aop.support.DefaultPointcutAdvisor;

/**
 * @author: AirMan
 * @date: 2025/4/14 16:22
 * @description:
 */
public class MyA15 {
    public static void main(String[] args) {

        // 1.准备切点 PointCut
        AspectJExpressionPointcut pointcut = new AspectJExpressionPointcut();
        pointcut.setExpression("execution(* foo()) || execution(* bar())");

        // 2.准备通知 Advice
        MethodInterceptor advice = new MethodInterceptor() {
            @Override
            public Object invoke(MethodInvocation jointPoint) throws Throwable {
                System.out.println("before...");
                Object result = jointPoint.proceed();
                System.out.println("after...");
                return result;
            }
        };

        // 3.准备切面 Aspect
        DefaultPointcutAdvisor aspect = new DefaultPointcutAdvisor();
        aspect.setPointcut(pointcut);
        aspect.setAdvice(advice);

        // 4.通过 ProxyFactory 创建代理对象
        Target1 target = new Target1();
        ProxyFactory factory = new ProxyFactory();
        factory.setTarget(target);
        factory.addAdvisor(aspect);

        // 4.1测试 ProxyFactory 的动态代理生成方式
        // a. proxyTargetClass = false, 目标实现了接口, 用 jdk 实现
        /*factory.setProxyTargetClass(false);
        factory.setInterfaces(target.getClass().getInterfaces());*/
        // b. proxyTargetClass = false,  目标没有实现接口, 用 cglib 实现
        /*factory.setProxyTargetClass(false);
        factory.setInterfaces(target.getClass().getInterfaces());*/
        // c. proxyTargetClass = true, 总是使用 cglib 实现
        factory.setProxyTargetClass(true);
        factory.setInterfaces(target.getClass().getInterfaces());
        // 4.2创建代理对象
        I1 proxy = (I1) factory.getProxy();
//        Target2 proxy = (Target2) factory.getProxy();


        // 5.调用增强方法
        System.out.println(proxy.getClass());
        System.out.println("---------------------");
        proxy.foo();
        System.out.println("---------------------");
        proxy.bar();
    }

    interface I1 {
        void foo();

        void bar();
    }

    static class Target1 implements I1 {
        public void foo() {
            System.out.println("target1 foo");
        }

        public void bar() {
            System.out.println("target1 bar");
        }
    }

    static class Target2 {
        public void foo() {
            System.out.println("target2 foo");
        }

        public void bar() {
            System.out.println("target2 bar");
        }
    }
}
